package com.qubuyer.core.ext

import android.content.Context
import android.net.ConnectivityManager
import androidx.annotation.StringRes
import androidx.lifecycle.LifecycleOwner
import com.hjq.toast.ToastUtils
import com.qubuyer.core.app.BaseApplication
import com.qubuyer.core.app.ContextProvider
import com.qubuyer.core.app.IBaseView
import com.qubuyer.core.utils.GsonUtil
import me.jessyan.autosize.utils.AutoSizeUtils
import me.jessyan.autosize.utils.ScreenUtils
import java.math.RoundingMode
import java.text.DecimalFormat
import java.text.NumberFormat

/**
 * Author: linwg
 * Time: 2021/2/2 0002
 * Description:
 */
val application: BaseApplication
    get() = ContextProvider.applicationContext

val Int.dp: Int
    get() {
        return AutoSizeUtils.dp2px(application, this.toFloat())
    }

val Float.dp: Int
    get() {
        return AutoSizeUtils.dp2px(application, this)
    }

val Int.sp: Int
    get() {
        return AutoSizeUtils.sp2px(application, this.toFloat())
    }

val Float.sp: Int
    get() {
        return AutoSizeUtils.sp2px(application, this)
    }

val Float.toDp: Float
    get() = this / application.resources.displayMetrics.density

val Int.toDp: Float
    get() = this / application.resources.displayMetrics.density

val Float.toSp: Float
    get() = this / application.resources.displayMetrics.scaledDensity

val Int.toSp: Float
    get() = this / application.resources.displayMetrics.scaledDensity

val screenSize: IntArray
    get() = ScreenUtils.getScreenSize(application)

object Cache {
    val map = HashMap<String, Any>()
}

val screenWidth: Int
    get() {
        return Cache.map["screenWidth"] as Int?
            ?: screenSize[0].also { sw -> Cache.map["screenWidth"] = sw }
    }

val screenHeight: Int
    get() {
        return Cache.map["screenHeight"] as Int?
            ?: screenSize[1].also { sh -> Cache.map["screenHeight"] = sh }
    }

fun networkValid(): Boolean {
    val cm = application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val info = cm.activeNetworkInfo
    return (info != null) && info.isAvailable && info.isConnected
}

fun LifecycleOwner.toast(msg: CharSequence?) {
    msg?.let { ToastUtils.show(it) }
}

fun LifecycleOwner.toast(@StringRes msgRes: Int) {
    ToastUtils.show(msgRes)
}

fun LifecycleOwner.showHttpRequestProgressDialog(msg: String? = null) {
    if (this is IBaseView) {
        this.showProgressDialog(msg)
    }
}

fun LifecycleOwner.hideHttpRequestProgressDialog() {
    if (this is IBaseView) {
        this.hideProgressDialog()
    }
}

fun LifecycleOwner.handlerNetworkInvalidMessage() {
    if (this is IBaseView) {
        this.processNetworkInvalid()
    }
}

fun LifecycleOwner.handlerTokenInvalidMessage() {
    if (this is IBaseView) {
        this.processTokenInvalid()
    }
}

fun Any?.toJson(): String {
    return if (this == null) "" else GsonUtil.toJson(this)
}

inline fun <reified T> fromJson(json: String, clazz: Class<T> = T::class.java): T {
    return GsonUtil.gson.fromJson(json, clazz)
}

fun Double?.format(
    fractionDigits: Int = 1,
    minIntegerDigits: Int = 1,
    isGrouping: Boolean = false,
    isHalfUp: Boolean = true
): CharSequence {
    if(this == null){
        return "0.00"
    }
    val nf: DecimalFormat = NumberFormat.getInstance() as DecimalFormat
    nf.isGroupingUsed = isGrouping
    nf.roundingMode = if (isHalfUp) RoundingMode.HALF_UP else RoundingMode.DOWN
    nf.minimumIntegerDigits = minIntegerDigits
    nf.minimumFractionDigits = fractionDigits
    nf.maximumFractionDigits = fractionDigits
    return nf.format(this)
}

fun String?.numberFormat(
    fractionDigits: Int = 1,
    minIntegerDigits: Int = 1,
    isGrouping: Boolean = false,
    isHalfUp: Boolean = true
): CharSequence {
    if (this.isNullOrEmpty()) {
        return "0.00"
    }
    return try {
        this.toDouble().format(fractionDigits, minIntegerDigits, isGrouping, isHalfUp)
    } catch (e: Exception) {
        "0.00"
    }
}